﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cofe.Core;
using Cofe.Core.Entry;
using Cofe.Core.Filter;
using Cofe.Core.Implements;
using Cofe.Core.Interfaces;
using Cofe.Core.Property;
using Cofe.Core.Service;

namespace Cofe.Data
{
    public class RepositorySearchActionProvider : SearchActionProvider
    {
        #region Factory
        [Export(typeof(ICofeService))]
        [ServicePriority(ServicePriorityAttribute.DefaultPriority_COFEDB)]
        public new class Factory : ISecondaryPropertyProviderFactory, INotifyImported
        {
            public IEnumerable<IPropertyProvider> GetSecoondaryPropertyProviders(IPropertyHost propertyHost)
            {
                bool isSearch = propertyHost.Behaviors.IsPropertySupported(CofeEntryListProperties.FilterString);

                if (!(propertyHost.SecondaryPropertyProviders.Any((p) => p is ISearchActionProvider)) && isSearch)
                    yield return new RepositorySearchActionProvider(propertyHost);
            }

            public void OnImported(IServiceLocater serviceLocater)
            {
                _repositoryFactory = serviceLocater.TryFindService<IRepositoryFactory>();
            }

            private IRepositoryFactory _repositoryFactory = null;
            private IServiceLocater _serviceLocater = null;

            public IServiceLocater ServiceLocater
            {
                get { return _serviceLocater ?? CofeServices.ServiceLocater; }
                set { _serviceLocater = value; }
            }



        }
        #endregion

        #region Constructor

        public RepositorySearchActionProvider(IPropertyHost propertyHost)
            : base(propertyHost, CofeServices.EntryConstructor)
        {

        }

        #endregion

        #region Methods

        protected override void search(ParameterDic parameters)
        {
            IPropertyHost eph = Entity;
            IEntryFilter[] entryFilters; IOptionFilter[] optionFilters;
            string filterStr = this.Entity.Behaviors.GetProperty<string>(CofeEntryListProperties.FilterString);
            CofeServices.EntryFilterParser.ParseFilter(filterStr, out entryFilters, out optionFilters);
            var paginate = optionFilters.FirstOrDefault(f => f is PaginateOptionFilter) as PaginateOptionFilter;

            parameters.IsHandled = true;
            using (var repository = RepositoryFactory.CreateRepository())
            {
                var filters = FilterCollections.FromFilters(entryFilters, optionFilters);
                _entryList = repository.FindAll(filters).ToList();

                if (paginate != null)
                {
                    var count = repository.Count(filters);
                    parameters.AddOrUpdate(ParameterKeys.CurrentPage, paginate.Page);
                    parameters.AddOrUpdate(ParameterKeys.TotalPages, (int)Math.Ceiling((float)count / paginate.ItemsPerPage));
                    parameters.AddOrUpdate(ParameterKeys.TotalEntries, count);
                    parameters.AddOrUpdate(ParameterKeys.ItemsPerPage, paginate.ItemsPerPage);
                }
            }
        }

        #endregion

        #region Data

        private IRepositoryFactory _repositoryFactory = null;

        #endregion

        #region Public Properties

        public IRepositoryFactory RepositoryFactory { get { return _repositoryFactory ?? (_repositoryFactory = CofeServices.ServiceLocater.FindService<IRepositoryFactory>()); } }
        #endregion

    }
}
